package com.yangchuang.openpicture.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yangchuang.openpicture.communication.ResultCode;
import com.yangchuang.openpicture.constant.JwtTokenClaimsConstants;
import com.yangchuang.openpicture.constant.TokenConstants;
import com.yangchuang.openpicture.constant.UserLoginReturnConstants;
import com.yangchuang.openpicture.dto.UserForgetPasswordDTO;
import com.yangchuang.openpicture.dto.UserLogoutDTO;
import com.yangchuang.openpicture.dto.UserRefreshTokenDTO;
import com.yangchuang.openpicture.dto.UserRegisterDTO;
import com.yangchuang.openpicture.dto.UserUpdatePersonalInfoDTO;
import com.yangchuang.openpicture.exception.BussinessException;
import com.yangchuang.openpicture.mapper.UserFavoriteFolderMapper;
import com.yangchuang.openpicture.mapper.UserMapper;
import com.yangchuang.openpicture.pojo.User;
import com.yangchuang.openpicture.pojo.UserFavoriteFolder;
import com.yangchuang.openpicture.service.EmailService;
import com.yangchuang.openpicture.service.TokenBlacklistService;
import com.yangchuang.openpicture.service.UserService;
import com.yangchuang.openpicture.util.JwtUtil;
import com.yangchuang.openpicture.vo.LoginReturnUserVO;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final UserMapper userMapper;
    private final JwtUtil jwtUtil;
    private final EmailService emailService;
    private final TokenBlacklistService tokenBlacklistService;
    private final UserFavoriteFolderMapper userFavoriteFolderMapper;


    @Override
    public Map<String, Object> login(String email, String password) {
        //不用根据email和password一起去查  只根据email去查询即
        User user = userMapper.getUserByEmail(email);
        log.info("用户登录：{}", user);
        //对密码进行加密 然后比较
        if (user == null || !DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8)).equals(user.getPassword())) {
            throw new BussinessException(ResultCode.LOGIN_FAILED);
        }
        //登陆成功 返回两个token
        Map<String, Object> map = new HashMap<>();
        String userid = String.valueOf(user.getId());
        String accessToken = jwtUtil.createAccessToken(userid, user.getUserRole());
        String refreshToken = jwtUtil.createRefreshToken(userid);
        map.put(TokenConstants.ACCESS_TOKEN, accessToken);
        map.put(TokenConstants.REFRESH_TOKEN, refreshToken);
        //添加登录用户的脱敏信息给前端
        LoginReturnUserVO loginReturnUserVO = new LoginReturnUserVO();
        BeanUtils.copyProperties(user, loginReturnUserVO);
        map.put(UserLoginReturnConstants.LOGIN_USER_INFO, loginReturnUserVO);
        return map;
    }


    /**
     * 新增用户 ，并且为用户创建了一个默认的收藏夹
     *
     * @param userRegisterDTO 用户注册发过来的相关信息
     */
    @Override
    public void register(UserRegisterDTO userRegisterDTO) {
        //1.检查两个密码是否一直
        String password = userRegisterDTO.getPassword();
        String checkPassword = userRegisterDTO.getCheckPassword();
        if (!password.equals(checkPassword)) {
            throw new BussinessException(ResultCode.DIFFERENT_PASSWORD);
        }
        //2.检查验证码是否正确
        String email = userRegisterDTO.getEmail();
        String verifyCode = userRegisterDTO.getVerifyCode();
        if (!emailService.verifyCode(email, verifyCode)) {
            throw new BussinessException(ResultCode.WRONG_CHECKCODE);
        }
        //3.检查邮箱是否已经存在
        User userByEmail = userMapper.getUserByEmail(email);
        if (userByEmail != null) {
            throw new BussinessException(ResultCode.REPEATED_EMAIL);
        }
        //4.注册成功 插入数据
        User user = new User();
        user.setUsername(RandomStringUtils.random(10, true, true));
        user.setEmail(email);
        user.setPassword(DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8)));
        userMapper.insert(user);
        //todo 用户注册成功，为每一个注册成功的用户默认创建一个 默认的收藏夹
        UserFavoriteFolder userFavoriteFolder = new UserFavoriteFolder();
        userFavoriteFolder.setName("默认的收藏夹");
        userFavoriteFolder.setUserId(user.getId());
    }

    @Override
    public void logout(UserLogoutDTO userLogOutDTO) {
        //自己会检查剩余时间 并且设置有效期=token的剩余时间
        if (userLogOutDTO.getAccessToken() != null) {
            tokenBlacklistService.addToBlacklist(userLogOutDTO.getAccessToken());
        }
        if (userLogOutDTO.getRefresToken() != null) {
            tokenBlacklistService.addToBlacklist(userLogOutDTO.getRefresToken());
        }
    }

    @Override
    public User getprofile(String id) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getId, Long.parseLong(id));
        User user = userMapper.selectOne(wrapper);
        if (user == null) {
            throw new BussinessException(ResultCode.USER_NOT_FOUND);
        }
        return user;
    }


    /**
     * 更新用户头像
     *
     * @param currentUserId 当前用户ID
     * @param avatarUrl     头像URL
     */
    @Override
    public void updateAvatar(String currentUserId, String avatarUrl) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getId, Long.parseLong(currentUserId));
        User user = userMapper.selectOne(wrapper);
        if (user == null) {
            throw new BussinessException(ResultCode.USER_NOT_FOUND);
        }
        user.setAvatar(avatarUrl);
        userMapper.updateById(user);
    }

    /**
     * 更新用户个人信息
     *
     * @param currentUserId             当前用户ID
     * @param userUpdatePersonalInfoDTO 用户更新个人信息DTO
     */
    @Override
    public void updatePersonalInfo(String currentUserId, UserUpdatePersonalInfoDTO userUpdatePersonalInfoDTO) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getId, Long.parseLong(currentUserId));
        User user = userMapper.selectOne(wrapper);
        if (user == null) {
            throw new BussinessException(ResultCode.USER_NOT_FOUND);
        }

        // 更新用户信息
        if (userUpdatePersonalInfoDTO.getUsername() != null && !userUpdatePersonalInfoDTO.getUsername().isEmpty()) {
            user.setUsername(userUpdatePersonalInfoDTO.getUsername());
        }
        if (userUpdatePersonalInfoDTO.getGender() != null) {
            user.setGender(userUpdatePersonalInfoDTO.getGender());
        }
        if (userUpdatePersonalInfoDTO.getAvatar() != null && !userUpdatePersonalInfoDTO.getAvatar().isEmpty()) {
            user.setAvatar(userUpdatePersonalInfoDTO.getAvatar());
        }

        userMapper.updateById(user);
    }

    @Override
    public void resetPassword(UserForgetPasswordDTO userForgetPasswordDTO) {
        //用户忘记密码---重置密码
        //1. 检验两次密码是否相同
        String password = userForgetPasswordDTO.getPassword();
        String checkPassword = userForgetPasswordDTO.getCheckPassword();
        if (!password.equals(checkPassword)) {
            throw new BussinessException(ResultCode.DIFFERENT_PASSWORD);
        }
        //2. 检验验证码是否正确
        String verifyCode = userForgetPasswordDTO.getVerifyCode();
        String email = userForgetPasswordDTO.getEmail();
        if (!emailService.verifyCode(email, verifyCode)) {
            throw new BussinessException(ResultCode.WRONG_CHECKCODE);
        }
        //验证码正确了 执行更新操作
        User userByEmail = userMapper.getUserByEmail(email);
        if (userByEmail == null) {
            throw new BussinessException(ResultCode.USER_NOT_FOUND);
        }
        //更新用户密码
        userMapper.updateUserPasswordByEmail(email, DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8)));
    }

    @Override
    public Map<String, String> refreshToken(UserRefreshTokenDTO userRefreshTokenDTO) {
        String refreshtoken = userRefreshTokenDTO.getRefreshtoken();
        Claims claims = jwtUtil.parseToken(refreshtoken);//不报错 就说明refreshtoken是ok的
        String userid = (String) claims.get(JwtTokenClaimsConstants.USER_ID);
        User user = userMapper.getUserById(userid);
        if (user == null) {
            throw new BussinessException(ResultCode.INTERNAL_ERROR);
        }
        //把旧的token加入redis的黑名单中
        tokenBlacklistService.addToBlacklist(refreshtoken);
        String refreshToken = jwtUtil.createRefreshToken(userid);
        String accessToken = jwtUtil.createAccessToken(userid, user.getUserRole());
        Map<String, String> map = new HashMap<>();
        map.put(TokenConstants.ACCESS_TOKEN, accessToken);
        map.put(TokenConstants.REFRESH_TOKEN, refreshToken);
        return map;

    }
}
